package discov

import (
	"fmt"
	"gitee.com/gaodihu/gsf/core/logx"
	"gitee.com/gaodihu/gsf/core/util"
	"log"
	"strings"

	"github.com/pkg/errors"

	consulapi "github.com/hashicorp/consul/api"
)

type (
	PublisherOption func(client *Publisher)

	Publisher struct {
		consulHost string
		consulKey  string
		fullKey    string
		listenOn   string
		listenPort int
		isSecure   bool
		tags       []string
		serviceId         string
		client     *consulapi.Client
	}
)

const (
	allEths  = "0.0.0.0"
	envPodIp = "POD_IP"
)

func NewPublisher(consulHost string, consulKey string, listenOn string, listenPort int, isSecure bool, opts ...PublisherOption) *Publisher {
	publisher := &Publisher{
		consulHost: consulHost,
		consulKey:  consulKey,
		listenOn:   listenOn,
		listenPort: listenPort,
		isSecure:   isSecure,
	}

	for _, opt := range opts {
		opt(publisher)
	}

	return publisher
}

func (p *Publisher) Register() error {
	config := consulapi.DefaultConfig()
	config.Address = p.consulHost

	ip := figureOutListenOn(p.listenOn)
	port := p.listenPort

	scheme := "http"
	if p.isSecure {
		scheme = "https"
		p.tags = append(p.tags, "secure=true")
	} else {
		p.tags = append(p.tags, "secure=false")
	}
	p.tags = append(p.tags, p.consulKey)

	id := figureOuId(p.consulKey, ip, port)
	reg := consulapi.AgentServiceRegistration{}

	p.serviceId = id

	reg.Name = p.consulKey //注册service的名字
	reg.Address = ip       //注册service的ip
	reg.Port = port        //注册service的端口
	reg.Tags = p.tags
	reg.ID = id


	check := consulapi.AgentServiceCheck{} //创建consul的检查器
	check.Interval = "5s"                  //设置consul心跳检查时间间隔
	check.HTTP = fmt.Sprintf("%s://%s:%d/%s", scheme, ip, port, "health")

	reg.Check = &check

	client, err := consulapi.NewClient(config) //创建客户端
	if err != nil {
		log.Fatal(err)
	}
	p.client = client
	err = client.Agent().ServiceRegister(&reg)
	return errors.Wrap(err, "consul register err")
}
func (p *Publisher) Revoke()  {
	if p.client == nil {
		 logx.Error("consul client is nil")
	}
	err := p.client.Agent().ServiceDeregister(p.serviceId)
	if err != nil {
		logx.ErrorWithStack(err)
	}else{
		logx.Info("Deregister")
	}

}

func figureOutListenOn(listenOn string) (ip string) {
	if len(listenOn) == 0 || listenOn == allEths {
		ip = util.LocalIp()
	} else {
		ip = listenOn
	}

	return
}
func figureOuId(name,host string ,port int) string {
	host = strings.ReplaceAll(host,".","-")
	return fmt.Sprintf("%s-%s-%d", name,host,port)
}
